#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

using namespace std;

const int SIZE_OF_BUFFER = 5;
int ProductID = 0;
int ConsumeID = 0;
int in = 0;              //产品进缓冲区时的缓冲区下标   
int out = 0;             //产品出缓冲区时的缓冲区下标   

int g_buffer[SIZE_OF_BUFFER];  //缓冲区是个循环队列   
bool g_continue = true;

pthread_mutex_t g_mutex;  // 互斥锁
sem_t g_fullSemaphore;    // 满缓冲区信号量
sem_t g_emptySemaphore;   // 空缓冲区信号量

//生产一个产品。把新生产的产品放入缓冲区   
void Produce()   
{   
    cout << "生产了一个产品:" << ++ProductID << endl;
    g_buffer[in] = ProductID;   
    in = (in + 1) % SIZE_OF_BUFFER;   

    // 输出缓冲区当前的状态   
    for (int i = 0; i < SIZE_OF_BUFFER; ++i) {   
        cout << i << ":   " << g_buffer[i];   
        if (i == in) cout << "   <--   生产";   
        if (i == out) cout << "   <--   消费";   
        cout << endl;   
    }
    cout << endl;   
}   

// 从缓冲区中取出一个产品，消耗一个产品   
void Consume()   
{   
    cout << "消耗了一个产品:" << g_buffer[out] << endl;
    g_buffer[out] = 0;		  
    out = (out + 1) % SIZE_OF_BUFFER;     

    // 输出缓冲区当前的状态   
    for (int i = 0; i < SIZE_OF_BUFFER; ++i) {   
        cout << i << ":   " << g_buffer[i];   
        if (i == in) cout << "   <--   生产";   
        if (i == out) cout << "   <--   消费";   
        cout << endl;   
    } 
    cout << endl;  
}

// 生产者线程   
void* Producer(void* lpPara)   
{   
    while (g_continue) {   
        sem_wait(&g_emptySemaphore);  // 申请空缓冲区
        pthread_mutex_lock(&g_mutex); // 互斥访问缓冲区
        Produce();   
        usleep(2000000);  // 休眠2秒   
        pthread_mutex_unlock(&g_mutex);   
        sem_post(&g_fullSemaphore);   // 释放满缓冲区信号量
    }   
    return nullptr;   
}   

// 消费者线程   
void* Consumer(void* lpPara)   
{   
    while (g_continue) {   
        sem_wait(&g_fullSemaphore);   // 申请满缓冲区
        pthread_mutex_lock(&g_mutex);  // 互斥访问缓冲区
        Consume();   
        usleep(2000000);  // 休眠2秒   
        pthread_mutex_unlock(&g_mutex);   
        sem_post(&g_emptySemaphore);   // 释放空缓冲区信号量
    }   
    return nullptr;   
}  

int main()   
{   
    // 初始化互斥锁和信号量
    pthread_mutex_init(&g_mutex, nullptr);
    sem_init(&g_fullSemaphore, 0, 0);       // 满缓冲区信号量初始化为0
    sem_init(&g_emptySemaphore, 0, SIZE_OF_BUFFER);  // 空缓冲区信号量初始化为缓冲区大小

    const int PRODUCERS_COUNT = 6;     // 生产者的个数   
    const int CONSUMERS_COUNT = 2;     // 消费者的个数   

    const int THREADS_COUNT = PRODUCERS_COUNT + CONSUMERS_COUNT;   
    
    pthread_t hThreads[THREADS_COUNT];   // 各线程的handle   
   
    // 创建生产者线程   
    for (int i = 0; i < PRODUCERS_COUNT; ++i) {   
        if (pthread_create(&hThreads[i], nullptr, Producer, nullptr)) {
            cout << "生产者线程创建失败!" << endl;
            return -1;
        }
    }   

    // 创建消费者线程   
    for (int j = 0; j < CONSUMERS_COUNT; ++j) {   
        if (pthread_create(&hThreads[PRODUCERS_COUNT + j], nullptr, Consumer, nullptr)) {
            cout << "消费者线程创建失败!" << endl;
            return -1;
        }
    }

    // 等待用户输入以终止程序
    while (g_continue) {   
        if (getchar()) {  // 按回车后终止程序运行   
            g_continue = false;   
        }   
    }   

    // 等待所有线程结束
    for (int i = 0; i < THREADS_COUNT; ++i) {
        pthread_join(hThreads[i], nullptr);
    }

    // 清理资源
    pthread_mutex_destroy(&g_mutex);
    sem_destroy(&g_fullSemaphore);
    sem_destroy(&g_emptySemaphore);

    return 0;   
}   
